package org.ocean.hibernate;

import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.lang.StringUtils;
import org.hibernate.EntityMode;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

public class BaseHibernateDao {
	protected SessionFactory sessionFactroy;

	public BaseHibernateDao() {
		this.sessionFactroy = SessionFactoryUtil.getSysSessionFactory();
	}

	public void save(Object obj){
		Session ss = this.sessionFactroy.openSession();
		ss = ss.getSession(EntityMode.MAP);
		
		Transaction tr = ss.beginTransaction();
		ss.save(obj);
		tr.commit();
		ss.close();
	}
	
	public void save(String entity,Map data){
		Session ss = this.sessionFactroy.openSession();
		ss.getSession(EntityMode.MAP);
		Transaction tr = ss.beginTransaction();
		if(data.get("uid")==null){
			data.put("uid", UUID.randomUUID().toString());
		}
		ss.save(entity,data);
		tr.commit();
		ss.close();
	}
	
	public void delete(Object obj){
		Session ss = this.sessionFactroy.openSession();
		Transaction tr = ss.beginTransaction();
		ss.delete(obj);
		tr.commit();
		ss.close();
	}
	
	@SuppressWarnings("unchecked")
	public <X> List<X> find(String hql, Map<String, Object> values) {
		return createQuery(hql, values).list();
	}
	
	@SuppressWarnings("unchecked")
	public <X> List<X> find(String hql, Object... values) {
		return createQuery(hql, values).list();
	}
	
	@SuppressWarnings("unchecked")
	public Object findUnique(String hql, Object... values) {
		List<Object> list = createQuery(hql, values).list();
		if(list==null || list.size()==0){
			return null;
		}
		return list.get(0);
	}
	
	public <T> Page<T> findPage(Page<T> page, String hql, Object... values)
	  {
	    Query q = createQuery(hql, values);
	    if (page.isAutoCount()) {
	      long totalCount = countHqlResult(hql, values);
	      page.setTotalCount(totalCount);
	    }
	    q.setFirstResult(page.getFirstOfPage() - 1);
	    q.setMaxResults(page.getPageSize());
	    page.setResult(q.list());
	    return page;
	  }
	
	public Query createQuery(String queryString, Object... values)
	  {
	    Query query = getSession().createQuery(queryString);
	    if (values != null) {
	      for (int i = 0; i < values.length; ++i) {
	        query.setParameter(i, values[i]);
	      }
	    }
	    return query;
	  }
	
	public Query createQuery(String queryString, Map<String, Object> values)
	  {
	    Query query = getSession().createQuery(queryString);
	    if (values != null) {
	      query.setProperties(values);
	    }
	    return query;
	  }
	public Session getSession(){
		return this.sessionFactroy.openSession();
	}
	
	 public long countHqlResult(String hql, Map<String, Object> values)
	  {
	    Long count = Long.valueOf(0L);
	    String fromHql = hql;

	    fromHql = "from " + StringUtils.substringAfter(fromHql, "from");
	    fromHql = StringUtils.substringBefore(fromHql, "order by");

	    String countHql = "select count(*) " + fromHql;
	    try
	    {
	      count = (Long)createQuery(countHql, values).uniqueResult();
	    } catch (Exception e) {
	      throw new RuntimeException("hql can't be auto count, hql is:" + countHql, e);
	    }

	    return count.longValue();
	  }
	 
	 public long countHqlResult(String hql, Object... values)
	  {
	    Long count = Long.valueOf(0L);
	    String fromHql = hql;

	    fromHql = "from " + StringUtils.substringAfter(fromHql, "from");
	    fromHql = StringUtils.substringBefore(fromHql, "order by");

	    String countHql = "select count(*) " + fromHql;
	    try
	    {
	      count = (Long)createQuery(countHql, values).uniqueResult();
	    } catch (Exception e) {
	      throw new RuntimeException("hql can't be auto count, hql is:" + countHql, e);
	    }
	    if(count==null){
	    	return 0;
	    }
	    return count.longValue();
	  }
}
